﻿using WordSmith_V1.Library.Interfaces.Security;

namespace WordSmith_V1.Library.Security
{
    public class HashGenerator
    {
        private readonly IHash _hashFunction;

        private HashGenerator()
        {
        }

        public HashGenerator(IHash hashFunction)
        {
            _hashFunction = hashFunction;
        }

        /// <summary>
        /// Generates a hashed password from the input and outputs the salt used. STORE THE SALT
        /// </summary>
        /// <param name="plainText">The password to has</param>
        /// <param name="salt">The salt used, which should be saved with the password</param>
        /// <returns>The hashed password & salt</returns>
        public virtual byte[] GenerateSaltedHash(byte[] plainText, out byte[] salt)
        {
            salt = HashFunction.GenerateSalt();
            var plainTextWithSaltBytes =
              new byte[plainText.Length + salt.Length];

            for (var i = 0; i < plainText.Length; i++)
            {
                plainTextWithSaltBytes[i] = plainText[i];
            }
            for (var i = 0; i < salt.Length; i++)
            {
                plainTextWithSaltBytes[plainText.Length + i] = salt[i];
            }
            var hash = HashFunction.HashPassword(plainTextWithSaltBytes, salt);
            return hash;
        }

        public virtual byte[] GenerateHashWithSalt(byte[] plainText, byte[] salt)
        {
            var plainTextWithSaltBytes =
              new byte[plainText.Length + salt.Length];

            for (var i = 0; i < plainText.Length; i++)
            {
                plainTextWithSaltBytes[i] = plainText[i];
            }
            for (var i = 0; i < salt.Length; i++)
            {
                plainTextWithSaltBytes[plainText.Length + i] = salt[i];
            }
            var hash = HashFunction.HashPassword(plainTextWithSaltBytes, salt);
            return hash;
        }

        public virtual bool Verify(byte[] plainText, byte[] salt, byte[] hash)
        {
            return HashFunction.Verify(plainText, salt, hash);
        }

        protected IHash HashFunction
        {
            get { return _hashFunction; }
        }
    }
}
